use std::{fs, path::PathBuf, io::{self, Write}};
use serde::Deserialize;
use reqwest::blocking::Client;

#[derive(Debug, Deserialize)]
pub struct RawConfig {
    pub access_token: Option<String>,
    pub owner: Option<String>,
    pub repo: Option<String>,
    pub remote: Option<String>,
}

#[derive(Debug)]
pub struct Config {
    pub access_token: String,
    pub owner: String,
    pub repo: String,
}

impl Config {
    pub fn ensure_exists() -> Result<(), Box<dyn std::error::Error>> {
        let path = RawConfig::config_path()?;
        if path.exists() {
            return Ok(());
        }

        clear_screen();
        println!("✨ 第一次运行，请输入你的 Gitee Access Token");
        println!("你可以在这里获取: https://gitee.com/profile/personal_access_tokens\n");

        print!("🔐 Access Token: ");
        io::stdout().flush()?;
        let mut token = String::new();
        io::stdin().read_line(&mut token)?;
        let token = token.trim();

        if token.is_empty() {
            return Err("Token 不能为空".into());
        }

        let owner = get_owner_from_token(token)?;
        let (_auto_owner, repo) = get_git_remote_repo("origin")
            .ok_or("无法从 git remote 获取仓库名")?;

        let config = format!(
            r#"access_token = "{}"
owner = "{}"
repo = "{}"
"#,
            token, owner, repo
        );
        fs::write(&path, config)?;
        println!("✅ 配置文件已保存：{}", path.display());
        Ok(())
    }

    pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
        let raw = RawConfig::load_from_file()?;
        let access_token = raw.access_token.ok_or("配置中缺少 access_token")?;
        let remote_name = raw.remote.as_deref().unwrap_or("origin");

        let (auto_owner, auto_repo) = get_git_remote_repo(remote_name)
            .ok_or("无法从 Git 获取 remote 仓库信息")?;

        let owner = match raw.owner {
            Some(o) => o,
            None => get_owner_from_token(&access_token)?,
        };

        let repo = raw.repo.unwrap_or(auto_repo);

        Ok(Config {
            access_token,
            owner,
            repo,
        })
    }
}

impl RawConfig {
    fn load_from_file() -> Result<Self, Box<dyn std::error::Error>> {
        let path = Self::config_path()?;
        let content = fs::read_to_string(path)?;
        let config: Self = toml::from_str(&content)?;
        Ok(config)
    }

    fn config_path() -> Result<PathBuf, Box<dyn std::error::Error>> {
        let home = dirs::home_dir().ok_or("无法获取用户主目录")?;
        Ok(home.join(".gitee-tui-pr.toml"))
    }
}

fn get_owner_from_token(token: &str) -> Result<String, Box<dyn std::error::Error>> {
    let url = format!("https://gitee.com/api/v5/user?access_token={}", token);
    let client = Client::new();
    let res = client.get(&url).send()?;
    let json: serde_json::Value = res.json()?;
    Ok(json["login"].as_str().unwrap_or_default().to_string())
}

fn get_git_remote_repo(remote_name: &str) -> Option<(String, String)> {
    let repo = git2::Repository::discover(".").ok()?;
    let remote = repo.find_remote(remote_name).ok()?;
    let url = remote.url()?.to_string();

    let re = regex::Regex::new(r"(?:[:/])([^/]+)/([^/.]+)(?:\.git)?$").ok()?;
    let caps = re.captures(&url)?;
    let owner = caps.get(1)?.as_str().to_string();
    let repo = caps.get(2)?.as_str().to_string();

    Some((owner, repo))
}

pub fn clear_screen() {
    use crossterm::{execute, terminal::{Clear, ClearType}};
    let mut stdout = std::io::stdout();
    execute!(stdout, Clear(ClearType::All)).unwrap();
}
